package com.angcyo.selenium.auto

import com.angcyo.library.ex.nowTime
import com.angcyo.library.ex.sleep
import com.angcyo.library.ex.toElapsedTime
import com.angcyo.log.L
import com.angcyo.selenium.PlaceholderWebElement
import com.angcyo.selenium.auto.action.StartAction
import com.angcyo.selenium.auto.parse.HandleResult
import com.angcyo.selenium.bean.ActionBean

/**
 * 用于执行[ActionBean]
 * Email:angcyo@126.com
 * @author angcyo
 * @date 2020/12/30
 */
class ActionSchedule(val control: BaseControl) {

    /**临时需要执行的[ActionBean]*/
    val tempActionList = mutableListOf<ActionBean>()

    /**下一个[ActionBean]需要执行的时间间隔*/
    var _nextTime: Long = 0

    /**当前执行到哪一步*/
    var actionIndex = -1

    //下一次需要执行的索引
    var _nextActionIndex = -1

    //强制指定下一个需要执行的索引
    var _targetActionIndex: Int? = null

    val nextActionBean: ActionBean?
        get() {
            val targetIndex = _targetActionIndex
            if (targetIndex != null) {
                actionIndex = targetIndex
                _nextActionIndex = targetIndex
            }
            return tempActionList.nextAction() ?: control._currentTaskBean?.actionList?.getOrNull(_nextActionIndex)
        }

    /**当前正在执行的[ActionBean]*/
    var _currentActionBean: ActionBean? = null

    /**执行开始的时间, 毫秒*/
    var _startTime: Long = 0

    /**执行结束的时间, 毫秒*/
    var _endTime: Long = 0

    /**运行次数统计, 从1开始计数*/
    var actionCount = hashMapOf<Long, ActionCount>()

    /**重置状态*/
    fun reset() {
        _startTime = 0
        _endTime = 0
        _nextTime = 0
        actionIndex = -1
        _nextActionIndex = -1
        _targetActionIndex = null
        actionCount.clear()
    }

    /**开始调度执行[ActionBean]*/
    fun schedule() {
        val driver = control.driver
        val task = control._currentTaskBean

        if (driver != null && task != null) {
            if (actionIndex < 0) {
                _nextActionIndex = 0
                _startTime = nowTime()
                StartAction().runAction(control, PlaceholderWebElement(), ActionBean(), "start")
            } else {
                //_nextActionIndex = _currentActionIndex + 1
                val nextAction = nextActionBean
                _targetActionIndex = null

                if (nextAction == null) {
                    //执行结束
                    actionIndex = control._currentTaskBean?.actionList?.size ?: actionIndex
                    //执行完毕
                    control.finish()
                } else {
                    var jumpAction = true //是否需要跳过执行
                    var jumpReason: String? = null //跳过原因

                    if (nextAction.check == null) {
                        jumpReason = "Action未指定check,跳过执行."
                        jumpAction = true
                    } else {
                        if (nextAction.enable) {
                            if (control._autoParse.parseCondition(control, nextAction.conditionList)) {
                                jumpAction = false
                            } else {
                                jumpAction = true
                                jumpReason = "不满足条件,跳过执行:$nextAction"
                            }
                        } else {
                            if (nextAction.autoEnable) {
                                if (control._autoParse.parseCondition(control, nextAction.conditionList)) {
                                    jumpAction = false
                                } else {
                                    jumpAction = true
                                    jumpReason = "未自动激活,跳过执行:$nextAction"
                                }
                            } else {
                                jumpAction = true
                                jumpReason = "未激活,跳过执行:$nextAction"
                            }
                        }
                    }

                    //run
                    if (jumpAction) {
                        control.logAction?.invoke(jumpReason ?: "跳过执行:$nextAction")
                        next(nextAction)
                    } else {
                        _currentActionBean = nextAction
                        scheduleAction(nextAction, control._currentTaskBean?.backActionList, true)
                    }
                }
            }

            //执行结束, 等待下一个执行周期的触发执行...
            actionIndex = _nextActionIndex
            _nextTime = nextActionTime()
            if (!control._controlState.get().isControlEnd()) {
                showControlNextTip()
            }
        }
    }

    /**结束调度*/
    fun scheduleEnd() {
        _endTime = nowTime()
        _currentActionBean = null
    }

    /**运行[actionBean]
     * [isPrimaryAction] 任务最主要的[ActionBean], 用来判断是否需要执行[com.angcyo.selenium.bean.TaskBean.before] [com.angcyo.selenium.bean.TaskBean.after]
     * */
    fun scheduleAction(
        actionBean: ActionBean,
        otherActionList: List<ActionBean>? = null,
        isPrimaryAction: Boolean = false
    ): HandleResult? {
        var result: HandleResult? = null

        try {

            //Task前置处理
            var beforeHandleResult: HandleResult? = null
            if (isPrimaryAction) {
                val beforeAction = control._currentTaskBean?.before
                if (beforeAction != null) {
                    control.logAction?.invoke("任务前置执行:${beforeAction}")
                    _runWait(beforeAction.start)
                    beforeHandleResult = control.runAction(beforeAction)
                }
            }

            //处理
            if (beforeHandleResult?.success != true) {

                //action前置处理
                val beforeAction = actionBean.before
                if (beforeAction != null) {
                    control.logAction?.invoke("前置执行:${beforeAction}")
                    _runWait(beforeAction.start)
                    beforeHandleResult = control.runAction(beforeAction)
                }

                //action处理
                if (beforeHandleResult?.success != true) {
                    control.logAction?.invoke("${if (isPrimaryAction) "[主线]" else ""}开始执行[${actionBean.actionId}]:${actionBean}")
                    if (isPrimaryAction) {
                        //执行统计
                        runCountIncrement(actionBean.actionId)
                    }

                    //run
                    result = control.runAction(actionBean, otherActionList, isPrimaryAction)

                    if (result?.success == true) {
                        //只有成功才打印日志, 否则日志太多
                        control.logAction?.invoke("执行结果[${actionBean.title}(${actionBean.actionId})]:${result.success}")
                    }

                    //action后置处理
                    val afterAction = actionBean.after
                    if (afterAction != null) {
                        control.logAction?.invoke("后置执行:${afterAction}")
                        _runWait(afterAction.start)
                        control.runAction(afterAction)
                    }
                }

            }

            //Task后置处理
            if (isPrimaryAction) {
                val afterAction = control._currentTaskBean?.after
                if (afterAction != null) {
                    control.logAction?.invoke("任务后置执行:${afterAction}")
                    _runWait(afterAction.start)
                    control.runAction(afterAction)
                }
            }

        } catch (e: Exception) {
            L.e("异常:$e")
            e.printStackTrace()
            control.logAction?.invoke("运行失败[${actionBean.title}]:$e")
        }

        return result
    }

    /**运行[ActionBean]之前, 需要等待的时长*/
    fun _runWait(time: String?) {
        if (!time.isNullOrEmpty()) {
            val t = control._autoParse.parseTime(time)
            if (t > 0) {
                control.logAction?.invoke("wait:[${t}]")
                sleep(t)
            }
        }
    }

    /**执行下一个*/
    fun next(currentRunActionBean: ActionBean? = _currentActionBean) {
        _currentActionBean = null
        var nextIndex = actionIndex + 1
        currentRunActionBean?.let {
            //从临时action中移除已经执行完成的action,如果有
            if (tempActionList.firstOrNull() == it) {
                tempActionList.removeFirstOrNull()
                nextIndex = actionIndex
            }
        }
        control.logAction?.invoke("指定执行目标[$nextIndex/${actionSize()}]:$nextActionBean")
        _nextActionIndex = nextIndex
    }

    /**指定下一个需要执行的[ActionBean]*/
    fun nextTarget(targetActionBean: ActionBean) {
        val targetIndex = control._currentTaskBean?.actionList?.indexOf(targetActionBean)
        targetIndex?.let {
            if (it != -1) {
                control.logAction?.invoke("强制执行目标[$it/${actionSize()}]:$targetActionBean")
                _targetActionIndex = it
            }
        }
    }

    fun clearTempAction() {
        tempActionList.clear()
    }

    fun addNextAction(bean: ActionBean) {
        if (!tempActionList.contains(bean)) {
            tempActionList.add(bean)
        }
    }

    /**设置下一个需要执行的[ActionBean]*/
    fun startNextAction(bean: ActionBean) {
        clearTempAction()
        addNextAction(bean)
        (control as? AutoControl)?.resume()
    }

    /**总共需要执行的[ActionBean]的数量*/
    fun actionSize() = control._currentTaskBean?.actionList?.sumBy { if (it.enable) 1 else 1 }
        ?: 0 + tempActionList.sumBy { if (it.enable) 1 else 1 }

    fun showControlNextTip() {
        val title = "${control._currentTaskBean?.title}${indexTip()}"
        val des = nextActionBean?.title
        control.tipAction?.invoke(ControlTip(title, des, _nextTime))
    }

    /**索引指示提示文本*/
    fun indexTip(): String {
        return if (actionIndex >= 0) {
            "(${actionIndex}/${actionSize()})"
        } else {
            ""
        }
    }

    /**下一个[ActionBean]需要执行的时间间隔*/
    fun nextActionTime(): Long {
        val actionBean = nextActionBean
        return if (actionBean?.enable == true) {
            control._autoParse.parseTime(actionBean.start)
        } else {
            0
        }
    }

    /**获取总共运行时长*/
    fun duration(): Long = _endTime - _startTime

    fun durationStr() = duration().toElapsedTime(pattern = intArrayOf(-1, 1, 1))

    /**累加运行次数*/
    fun runCountIncrement(actionId: Long) {
        val count = actionCount[actionId] ?: ActionCount()
        count.runCount.doCount()
        actionCount[actionId] = count
    }

    /**累加跳转次数*/
    fun jumpCountIncrement(actionId: Long) {
        val count = actionCount[actionId] ?: ActionCount()
        count.jumpCount.doCount()
        actionCount[actionId] = count
    }

    /**获取[ActionBean]的运行次数*/
    fun getRunCount(actionId: Long): Long = actionCount[actionId]?.runCount?.count ?: -1

    fun getJumpCount(actionId: Long): Long = actionCount[actionId]?.jumpCount?.count ?: -1
}